/*!
 * \file    Affichage_Menu.c
 * \brief   Fichier d'affichage du menu principal, peut gérer d'autre menu du même type
 *
 * \date	28/02/2012
 * \author	Franck Lenormand
 */

#include <stdlib.h>
#include "Affichage_Menu.h"
#include "Gestion_Systemes.h"

/**
 * \fn  Uint8 menu(SDL_Surface * ecran )
 * \brief affiche le menu en appelant les bonnes fonctions et gère les évènements
 *
 * \return rend la valeur du bouton appuyer
 */
Uint8 menu(SDL_Surface * ecran ) {
	Uint8 valeurRenvoye =0;
	Uint8 continuer=1;
	SDL_Surface * surfaceTexteMenu=NULL;
	Uint8 p=0;
	Uint8 i=0;
	SDL_Event evenement;
	SDL_Rect * positionTexteMenu=NULL;
	SDL_Rect * positionBoutonMenu=NULL;
	SDL_Rect * positionElementMenu=NULL;
	Uint16 largeurTexteMax = 0;
	Uint16 hauteurTexte = 0;

	Uint8 temp=0;

	SDL_Rect postemp;

	/*On indique les textes à mettre*/
	char menu[][2*TAILLE_MAX_TEXTE]= { {"Space Invaders"},{"Jouer"},{"Option"},{"Editeur"},{"Credits"},{"Bonus"},{"Quitter"} };
	Uint8 nombreElementMenu = (Uint8)(sizeof(menu)/(2*TAILLE_MAX_TEXTE));

	/* On initialise la position des éléments*/
		positionElementMenu = initPosition(nombreElementMenu);/*OK*/

	/*On initialise les surfaces de textes -> largeur MAX, hauteur*/
	surfaceTexteMenu = initTexteMenu(menu,nombreElementMenu,&largeurTexteMax,&hauteurTexte);/*OK*/

	positionTexteMenu = initPositionTexte(nombreElementMenu,positionElementMenu,surfaceTexteMenu);
	for(i=0; i<nombreElementMenu; i++) {
		postemp = positionTexteMenu[i];
	}

	positionBoutonMenu = initPositionBouton(nombreElementMenu,positionElementMenu,largeurTexteMax,hauteurTexte);
	for(i=0; i<nombreElementMenu; i++) {
		postemp = positionBoutonMenu[i];
	}

	/*On blitte les boutons*/
	actualisationFond(ecran);
	actualisationBouton(nombreElementMenu, positionBoutonMenu,largeurTexteMax,hauteurTexte,p,ecran);

	/*On blitte le texte*/
	actualisationTexte(nombreElementMenu, positionTexteMenu,surfaceTexteMenu,ecran);

	/*
	On attend le choix du joueur
	*/
	while(continuer){
		SDL_WaitEvent(&evenement);

		if(evenement.type==SDL_QUIT) {
			exit(EXIT_SUCCESS);
			continuer=0;
			valeurRenvoye = QUITTER;
		}

		if(evenement.key.keysym.sym==SDLK_ESCAPE) {
			exit(EXIT_SUCCESS);
			continuer=0;
			valeurRenvoye = QUITTER;
		}
		temp=evenement.type;
		temp=evenement.button.button;
		temp=SDL_MOUSEBUTTONDOWN;
		temp=SDL_BUTTON_LEFT;
		if(evenement.type==SDL_MOUSEBUTTONDOWN && evenement.button.button == SDL_BUTTON_LEFT) { /*On regarde quel bouton à été cliqué*/
			if((p=rechercheBouton(evenement,positionBoutonMenu,nombreElementMenu,largeurTexteMax,hauteurTexte))>0) {
				actualisationFond(ecran);
				actualisationBouton(nombreElementMenu, positionBoutonMenu,largeurTexteMax,hauteurTexte,p,ecran);
				actualisationTexte(nombreElementMenu, positionTexteMenu,surfaceTexteMenu,ecran);
				SDL_Delay(500);/*pour voir le choix sélectionner*/
				valeurRenvoye = JOUER;
				continuer = 0;
			}
		}
	}

	return valeurRenvoye;
}


/**
 * \fn  SDL_Rect * initPosition(const Uint8 nbelement)
 * \brief Initialisation des positions centrale qu'auront les éléments
 *
 * param[out] Un tableau de position dont la case 0 est la position du titre
 * param[in] nbelement le nombre d'élément dans le menu (titre+bouton)
 *
 */
SDL_Rect * initPosition(const Uint8 nbelement) {
	Uint8 i=0;
	SDL_Rect  * pos_temp ;
	SDL_Rect temp ;
	SDL_Rect * ptr_retour;
	Uint32 centreLargeur=LARGEUR/2;

	if(nbelement==0) {
		fprintf(stderr,"Pas d'élément du menu à initialisé: %s\n",SDL_GetError());
		exit(EXIT_FAILURE);
	}

	if((ptr_retour=(SDL_Rect *) malloc((nbelement)*sizeof(SDL_Rect)))==NULL) {
		fprintf(stderr,"Erreur de création des positions : %s\n",SDL_GetError());
		exit(EXIT_FAILURE);
	}



	/*on initialise les positions*/
	for(i=0; i<nbelement; i++) {
		/*pos_temp = (ptr_retour+(i*sizeof(SDL_Rect)));*/
		pos_temp = &ptr_retour[i];
		if(i==0) {   /*Traitement spécial du titre*/
			pos_temp->x=centreLargeur;
			pos_temp->y=(HAUTEUR)/8;
		} else {
			pos_temp->x=centreLargeur;
			pos_temp->y=(HAUTEUR/4+(3*HAUTEUR/4/(nbelement+1))*i);
		}
	}

	for(i=0; i<nbelement; i++) {
		temp=ptr_retour[i];
	}

	return ptr_retour;
}


/**
 * \fn  SDL_Rect * initPositionTexte(const Uint8 nbelement, const SDL_Rect * positionelmt, const SDL_Surface * surfaceTexte)
 * \brief Initialisation les positions du texte (du titre et des boutons), différent de la position des boutons
 *
 * param[in] nbelement le nombre d'élément dans le menu
 * param[in] positionelmt Un tableau de position dont la case 0 est la position du titre
 * param[in] surfaceTexte Un tableau de surfuce de texte dont la case 0 est le texte du titre
 *
 * \return un tableau de position ou devra être coller le texte
 */
SDL_Rect * initPositionTexte(const Uint8 nbelement, const SDL_Rect * positionelmt, const SDL_Surface * surfaceTexte) {
	Uint8 i=0;
	SDL_Rect pos_temp ;
	SDL_Rect  temp ;
	SDL_Surface surftemp;
	SDL_Rect * ptr_retour;

	if((ptr_retour=(SDL_Rect *) malloc((nbelement)*sizeof(SDL_Rect)))==NULL) {
		fprintf(stderr,"Erreur de création des positions du texte : %s\n",SDL_GetError());
		exit(EXIT_FAILURE);
	}

	for(i=0; i<nbelement; i++) {
		temp = positionelmt[i];
		surftemp = surfaceTexte[i];
		(ptr_retour[i].x) = (temp.x) - (surftemp.w)/2;
		(ptr_retour[i].y) = (temp.y) - (surftemp.h)/2;

		pos_temp = ptr_retour[i];
	}

	return ptr_retour;
}

/**
 * \fn  SDL_Rect * initPositionBouton(const Uint8 nbelement, const SDL_Rect * positionelmt, const Uint16 large, const Uint16 haute)
 * \brief Initialisation les positions des boutons, différent de la position du texte
 *
 * param[in] nbelement le nombre d'élément dans le menu
 * param[in] positionelmt Un tableau de position dont la case 0 est la position du titre
 * param[in] large la largeur d'un bouton
 * param[in] haute la hauteur d'un bouton
 *
 * \return un tableau de position ou devra être coller les boutons
 */
SDL_Rect * initPositionBouton(const Uint8 nbelement, const SDL_Rect * positionelmt, const Uint16 large, const Uint16 haute) {
	Uint8 i=0;
	Uint16 larg = (large)/2;
	Uint16 haut = (haute)/2;
	SDL_Rect  temp ;
	SDL_Rect * ptr_retour;

	if((ptr_retour=(SDL_Rect *) malloc((nbelement)*sizeof(SDL_Rect)))==NULL) {
		fprintf(stderr,"Erreur de création des positions des boutons : %s\n",SDL_GetError());
		exit(EXIT_FAILURE);
	}

	for(i=1; i<nbelement; i++) {
		temp = positionelmt[i];
		(ptr_retour[i].x) = (temp.x) - larg - LARGEURBOUTON;
		(ptr_retour[i].y) = (temp.y) - haut - HAUTEURBOUTON;
		temp=ptr_retour[i];
	}

	return ptr_retour;
}

/**
 * \fn  Uint8  rechercheBouton(const SDL_Event evenement, const SDL_Rect * tableauposition, const Uint8 taille, const Uint16 largeur, const Uint16 hauteur)
 * \brief Recherche quel bouton à été cliqué parmi plusieurs
 *
 * param[in] evenement Un évènement SDL
 * param[in] tableauposition Un tableau de position dont la case 0 est la position du titre
 * param[in] taille le nombre d'élément dans le tableau
 * param[in] largeur la largeur d'un bouton
 * param[in] hauteur la hauteur d'un bouton
 *
 * \return l'indice du bouton cliqué
 */
Uint8  rechercheBouton(const SDL_Event evenement, const SDL_Rect * tableauposition, const Uint8 taille, const Uint16 largeur, const Uint16 hauteur) {
	Uint32 posX = (Uint32)evenement.button.x;
	Uint32 posY = (Uint32)evenement.button.y;
	SDL_Rect temp;
	Uint8 retour=0;
	Uint8 j=0;

	for(j=1; j<taille; j++) {
		temp = tableauposition[j];
		if(posX<=(temp.x+largeur+2*LARGEURBOUTON) && posX>=temp.x && posY<=(temp.y+hauteur+2*HAUTEURBOUTON) && posY>=temp.y) {
			retour = j;
			break;
		}
	}

	return retour;
}


/**
 * \fn  SDL_Surface * initTexteMenu(const char  menu[][2*TAILLE_MAX_TEXTE], const Uint8 nombreElement, Uint16 * largeurTexteMax,Uint16 * hauteurTexte)
 * \brief Crée le texte et l'associe à l'élement surface, rassemblé dans un tableau
 *
 * param[in] menu Un tableau de string de taille 2*TAILLE_MAX_TEXTE qui représente le texte du menu
 * param[in] nombreElement le nombre d'élément dans le tableau
 * param[in,out] largeurTexteMax un pointeur sur l'emplacement ou stocker la largeur que fera un bouton
 * param[out] hauteurTexte un pointeur sur l'emplacement ou stocker la hauteur que fera un bouton
 *
 * \return un pointeur sur le tableau de surface qui représente le texte
 */
SDL_Surface * initTexteMenu(const char  menu[][2*TAILLE_MAX_TEXTE], const Uint8 nombreElement, Uint16 * largeurTexteMax,Uint16 * hauteurTexte) {
	SDL_Surface * retour=NULL;
	SDL_Surface surftemp;
	TTF_Font *policeTitre = NULL;
	TTF_Font *policeBouton = NULL;
	SDL_Surface texte;
	SDL_Color Noir = {0, 0, 0};
	SDL_Color Jaune= {255, 255, 0};
	Uint8 i=0;

	policeTitre = TTF_OpenFont("../polices/calibri.ttf", 70);
	policeBouton = TTF_OpenFont("../polices/calibri.ttf", 40);

	if((retour=(SDL_Surface *)malloc(nombreElement*sizeof(SDL_Surface)))==NULL) {
		fprintf(stderr,"Erreur de création des surfaces d'écritures : %s\n",SDL_GetError());
		exit(EXIT_SUCCESS);
	}

	for(i=0; i<nombreElement; i++) { /*les boutons*/
		if(i==0) {
			texte = *(TTF_RenderText_Blended(policeTitre,menu[i], Jaune));
		} else {
			texte = *(TTF_RenderText_Blended(policeBouton,menu[i], Noir));
			if(*largeurTexteMax==0) { /* On cherche la alrgeur que prendra le texte*/
				*(largeurTexteMax) = (texte.w);
			} else if(   (Uint8)(texte.w)  >   (*largeurTexteMax)  ) {
				*(largeurTexteMax) = (texte.clip_rect.w);
			}
		}
		retour[i]=texte;
	}/*for du parcours des éléments du menu*/

	if(nombreElement>0) {
		*hauteurTexte = (retour[1].h);
	}

	for(i=0; i<nombreElement; i++) {
		surftemp = retour[i];
	}


	TTF_CloseFont(policeTitre);
	TTF_CloseFont(policeBouton);

	return retour;
}

/**
 * \fn  void actualisationBouton(const Uint8 nbel, const SDL_Rect * positionBouton, const Uint16 largeur, const Uint16 hauteur, const Uint8 p, SDL_Surface * ecran)
 * \brief Affiche les boutons à l'écran, si un bouton est sélectionné, il sera de couleur différente
 *
 * param[in] nbel Un évènement qui est un clic gauche
 * param[in] positionBouton Un tableau de position dont la case 0 est la position du titre
 * param[in] largeur la largeur d'un bouton
 * param[in] hauteur la hauteur d'un bouton
 * param[in] p l'indice du bonton cliqué
 * param[in] ecran un pointeur sur la une surface SDL qui est l'ecran de l'application
 *
 */
void actualisationBouton(const Uint8 nbel, SDL_Rect * positionBouton, const Uint16 largeur, const Uint16 hauteur, const Uint8 p, SDL_Surface * ecran) {
	SDL_Color gris = {192,192,192};
	SDL_Color noir = {255,255,255};
	SDL_Color bleu = {170,20,255};
	SDL_Surface * inactif;
	SDL_Surface * actif;
	Uint8 i;

	inactif = SDL_CreateRGBSurface(SDL_HWSURFACE, largeur+2*LARGEURBOUTON, hauteur+2*HAUTEURBOUTON, 32, 0, 0, 0, 0);
	if(inactif==NULL) {
		fprintf(stderr,"Erreur de création du fond inactif : %s\n",SDL_GetError());
		exit(EXIT_SUCCESS);
	}


	actif = SDL_CreateRGBSurface(SDL_HWSURFACE, largeur+2*LARGEURBOUTON, hauteur+2*HAUTEURBOUTON, 32, 0, 0, 0, 0);
	if(actif==NULL) {
		fprintf(stderr,"Erreur de création du fond actif : %s\n",SDL_GetError());
		exit(EXIT_SUCCESS);
	}


	SDL_FillRect(inactif, NULL, SDL_MapRGB(inactif->format, gris.r, gris.g, gris.b));
	SDL_SetAlpha(inactif, SDL_SRCALPHA, 128);

	SDL_FillRect(actif, NULL, SDL_MapRGB(actif->format, bleu.r, bleu.g, bleu.b));
	SDL_SetAlpha(actif, SDL_SRCALPHA, 128);

	for(i=1; i<nbel; i++) {
		SDL_BlitSurface(inactif, NULL, ecran, &positionBouton[i]);
	}

	if(p) {
		SDL_BlitSurface(actif, NULL, ecran, &positionBouton[p]);
	}

	SDL_Flip(ecran);
	SDL_FreeSurface(actif);
	SDL_FreeSurface(inactif);

}

/**
 * \fn  void actualisationTexte(const Uint8 nbel, const SDL_Rect * positonTexteMenu, const SDL_Surface * surfaceTexteMenu, SDL_Surface * ecran)
 * \brief Affiche le texte à l'écran
 *
 * param[in] nbel le nombre d'élément dans le tableau
 * param[in] positonTexteMenu Un tableau de position dont la case 0 est la position du titre
 * param[in] surfaceTexteMenu Un tableau de position dont la case 0 est le texte du titre
 * param[in] ecran un pointeur sur la une surface SDL qui est l'ecran de l'application
 *
 */
void actualisationTexte(const Uint8 nbel, SDL_Rect * positonTexteMenu, SDL_Surface * surfaceTexteMenu, SDL_Surface * ecran) {
	Uint8 i;

	for(i=0; i<nbel; i++) {
		SDL_BlitSurface(&surfaceTexteMenu[i], NULL, ecran, &positonTexteMenu[i]);
	}

	SDL_Flip(ecran);
}

/**
 * \fn  void actualisationFond(SDL_Surface * ecran)
 * \brief Affiche le fond de l'écran
 *
 * param[in] ecran un pointeur sur la une surface SDL qui est l'ecran de l'application
 *
 */
void actualisationFond(SDL_Surface * ecran) {

	SDL_Surface *fond = NULL;
	SDL_Rect pos_fond;
	pos_fond.x=0;
	pos_fond.y=0;

	chargerImage(ecran, &fond, "../Images/fond_menu_800x600.bmp");
	SDL_BlitSurface(fond, NULL, ecran, &pos_fond);
	SDL_FreeSurface(fond);
	SDL_Flip(ecran);
}




